package pro.survey.analyzer;

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import pro.survey.analyzer.imp.window.ImportsWindow;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
import javafx.stage.FileChooser;
import javafx.scene.layout.VBox;
import javafx.scene.layout.VBoxBuilder;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import jfx.messagebox.MessageBox;
import pro.survey.analyzer.exceptions.InvalidNumberItemsAndValues;
import javax.print.attribute.standard.Copies;

/**
 *
 * @author Adrian
 */
public class GUIGenerator {

    public static final String FILE_EXTENSION_XLS = "*.xls";
    public static final String FILE_EXTENSION_XLSX = "*.xlsx";
    public static final int DEFAULT_HEIGHT = 600;
    public static final int DEFAULT_WEIGHT = 800;
    private static GUIGenerator instance = null;
    private Scene mainScene;
    private MenuItem printItem;
    private MenuItem printToPDFItem;
    private Stage stage;

    public Scene getMainScene() {
        return mainScene;
    }
    private ImportsWindow dialogWindow;

    protected GUIGenerator() {
    }

    /**
     *
     * @return GUIGenerator
     */
    public static GUIGenerator getInstance() {
        if (instance == null) {
            instance = new GUIGenerator();
        }
        return instance;
    }

    /**
     *
     * @param primaryStage
     */
    public void createScene(Stage primaryStage) {
        mainScene = new Scene(new BorderPane(), DEFAULT_WEIGHT, DEFAULT_HEIGHT);
        mainScene.setFill(Color.OLDLACE);

        generateMenu(mainScene, primaryStage);

        primaryStage.setTitle(getLocaleText(Trans.APP_NAME));
        primaryStage.setScene(mainScene);
        primaryStage.show();
    }

    public void generateMenu(Scene scene, final Stage primaryStage) {
        stage = primaryStage;
        MenuBar menuBar = new MenuBar();
        Menu menuFile = new Menu(getLocaleText(Trans.FILE));

        MenuItem importItem = new MenuItem(getLocaleText(Trans.IMPORT_FILE));
        importItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                final FileChooser fc = new FileChooser();
                FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(getLocaleText(Trans.FILE_EXTENSION), new String[]{FILE_EXTENSION_XLS, FILE_EXTENSION_XLSX});
                fc.getExtensionFilters().add(extFilter);
                File file = fc.showOpenDialog(primaryStage);
                if (file != null) {
                    DataSheetLoader loader = new DataSheetLoader();
                    loader.loadFile(file);
                    loader.loadDataFromFile();
                    MessageBox.show(primaryStage,
                            getLocaleText(Trans.COUNT_LOADED_LECTORS).concat(Integer.toString(loader.lectors.size())),
                            getLocaleText(Trans.MONIT_INFO),
                            MessageBox.ICON_INFORMATION | MessageBox.OK);
                }
            }
        });
        
        printItem = new MenuItem(getLocaleText(Trans.PRINT));
        printItem.setDisable(true);
        printItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                try {
                    print();
                } catch (PrinterException ex) {
                    Logger.getLogger(GUIGenerator.class.getName()).log(Level.SEVERE, null, ex);
                } catch (PrintException ex) {
                    Logger.getLogger(GUIGenerator.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(GUIGenerator.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        
        printToPDFItem = new MenuItem(getLocaleText(Trans.PRINT_TO_PDF));
        printToPDFItem.setDisable(true);
        printToPDFItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                printToPDF();
            }
        });
        
        MenuItem selectImport = new MenuItem(getLocaleText(Trans.SELECT_IMPORT));
        selectImport.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                createSelectImportForm();
            }
        });
        MenuItem exit = new MenuItem(getLocaleText(Trans.EXIT));
        exit.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                HibernateUtil.getSessionFactory().close();
                System.exit(0);
            }
        });
        menuFile.getItems().addAll(importItem, selectImport, printItem, printToPDFItem, exit);
        menuBar.getMenus().addAll(menuFile);
        ((BorderPane) scene.getRoot()).setTop(menuBar);
    }

    public String getLocaleText(String name) {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("pro.survey.analyzer.label");
        return resourceBundle.getString(name);
    }

    public void createSelectImportForm() {
        dialogWindow = ImportsWindow.getInstance();
        dialogWindow.init();
    }

    public void createCharts() {
        try {
            ScrollPane sp = new ScrollPane();
            sp.setHbarPolicy(ScrollBarPolicy.NEVER);
            sp.setVbarPolicy(ScrollBarPolicy.ALWAYS);
            sp.setFitToWidth(true);
            sp.setFitToHeight(true);
            List<BarChartWithNote> charts = AnalyticsEngine.getInstance().makeChartByQuestion();
            VBox vb = VBoxBuilder.create().spacing(10).
                    alignment(Pos.CENTER).children(AnalyticsEngine.getInstance().makeMainChart()).
                    padding(new Insets(10)).build();
            for (int i = 0; i < charts.size() / 2; i++) {
                HBox box = HBoxBuilder.create().spacing(10).alignment(Pos.CENTER).build();
                box.getChildren().addAll(charts.get(i * 2), charts.get((i * 2) + 1));
                vb.getChildren().add(box);
            }
            sp.setContent(vb);
            ((BorderPane) mainScene.getRoot()).setCenter(sp);
            GUIGenerator.getInstance().setPrintDisable(false);
        } catch (InvalidNumberItemsAndValues ex) {
            System.out.print(ex.getMessage());
        }
    }

    public void print() throws PrinterException, PrintException, IOException {
        WritableImage snapshot = ((ScrollPane) ((BorderPane) mainScene.getRoot()).getCenter()).getContent().snapshot(new SnapshotParameters(), null);
        RenderedImage renderedImage = SwingFXUtils.fromFXImage(snapshot, null);
        DocFlavor docFlavor = DocFlavor.INPUT_STREAM.PNG;

        PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
        attributes.add(new Copies(1));

        PrintService printServices[] = PrintServiceLookup.lookupPrintServices(
                docFlavor, attributes);
        if (printServices.length == 0) {
            throw new RuntimeException("PrintService for PNG not available!");
        }

        System.out.println("Got PrintService: " + printServices[0].getName());

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(renderedImage, "png", out);
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());

        // Show PrintDialog
        boolean print = PrinterJob.getPrinterJob().printDialog(attributes);

        if (print) {
            DocPrintJob job = printServices[0].createPrintJob();
            Doc doc = new SimpleDoc(in, docFlavor, null);
            job.print(doc, attributes);
            in.close();
        }

        System.out.println("Done PrintService: " + print);
    }
    
    public void setPrintDisable(Boolean value) {
        printItem.setDisable(value);
        printToPDFItem.setDisable(value);
    }
    
    public void printToPDF() {
        FileChooser fileChooser = new FileChooser();
        FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("PDF (*.pdf)", "*.pdf");
        fileChooser.getExtensionFilters().add(extFilter);
        File file = fileChooser.showSaveDialog(stage);
        
        WritableImage snapshot = ((ScrollPane) ((BorderPane) mainScene.getRoot()).getCenter()).getContent().snapshot(new SnapshotParameters(), null);
        BufferedImage bimg = SwingFXUtils.fromFXImage(snapshot, null);
        Document document = new Document();
        try {
            PdfWriter.getInstance(document,
                    new FileOutputStream(file.getAbsolutePath().concat(".pdf")));
            document.open();
            
            float scaler = ((document.getPageSize().getHeight()- document.topMargin()
                           - document.bottomMargin()) / bimg.getHeight()) * 100;
            Image image1 = Image.getInstance((java.awt.Image) bimg, java.awt.Color.WHITE);
            image1.scalePercent(scaler);
            image1.setAlignment(Image.ALIGN_CENTER);
            document.add(image1);
            document.close();
        } catch(Exception e){
          e.printStackTrace();
        }
    }
}
